<script setup lang='ts'>
import type { FormInstance } from "element-plus";
import { useEventListener } from "@vueuse/core";
import { ElNotification } from "element-plus";
import { debounce } from "es-toolkit";
import { onMounted, onUnmounted, ref, watch } from "vue";
import Lock from "~icons/ri/lock-fill";
import KeyHole from "~icons/ri/shield-keyhole-fill";
import User from "~icons/ri/user-3-fill";
import { authApi } from "@/api";
import { useRenderIcon } from "@/components/ReIcon/src/hooks";
import { $t } from "@/plugins/i18n";
import router from "@/router";
import { initRouter } from "@/router/utils";
import { useUserStore } from "@/stores/user";
import { apiCall } from "@/utils/http/apiCall";
import { operates, thirdParty } from "@/views/login/utils/enums";
import Motion from "@/views/login/utils/motion";
import { loginRules } from "../utils/rules";

// 账号密码
const form = ref({
    username: "admin",
    password: "Aa123456",
    captchaText: "",
});

// 免登录
const checked = ref(false);
watch(checked, (value) => {
    useUserStore().SET_IS_REMEMBERED(value);
});

// 获取验证码
const captchaId = ref("");
const captchaImage = ref("");
const getCaptcha = debounce(() => {
    apiCall(
        () => authApi.getSignInCaptcha(),
        (data) => {
            captchaId.value = data.captchaId;
            captchaImage.value = data.image;
        },
    );
}, 500, { edges: ["leading"] });

// 登录
const ruleFormRef = ref<FormInstance>(); // 表单实例
const loginLoading = ref(false); // 登录按钮loading
const onLogin = () => {
    ruleFormRef.value!.validate().then(() => {
        loginLoading.value = true;
        apiCall(
            () => useUserStore().loginByUserName({ ...form.value, captchaId: captchaId.value }),
            (data) => {
                initRouter().then(() => {
                    router.push({ path: "/welcome" }).catch(() => {
                        console.info("登录跳转, 这个错误是哪儿来的呢?");
                    });
                    ElNotification({
                        title: $t("login.loginSuccess"),
                        message: `${$t("login.welcomeBack")}, ${data.nickname}`,
                        type: "success",
                    });
                });
            },
            {
                onError: () => {
                    getCaptcha();
                },
                onFinally: () => {
                    loginLoading.value = false;
                },
            },
        );
    });
};

// 创建防抖的登录函数
const debouncedLogin = debounce(
    onLogin,
    500,
    { edges: ["leading"] },
);

// 监听键盘事件, 当按下回车键时触发登录
const cleanup = useEventListener(
    document,
    "keydown",
    ({ code }) => {
        if (["Enter", "NumpadEnter"].includes(code) && !loginLoading.value) {
            // bugfix 每次按下回车键时都会创建一个新的防抖函数实例，这样防抖功能就无法正常工作。正确的做法是创建一个防抖函数的引用，然后重复使用它
            debouncedLogin();
        }
    },
);

onMounted(() => {
    getCaptcha();
});

onUnmounted(() => {
    cleanup();
});
</script>

<template>
    <!-- 账号密码登录 -->
    <!-- validate-on-rule-change:false 避免切换语言时表单规则动态变化自动校验 -->
    <el-form
        ref="ruleFormRef"
        :model="form"
        :rules="loginRules"
        :validate-on-rule-change="false"
        size="large"
    >
        <!-- 账号 -->
        <Motion :delay="100">
            <el-form-item prop="username">
                <el-input
                    v-model="form.username"
                    :prefix-icon="useRenderIcon(User)"
                    :placeholder="$t('login.username')"
                    clearable
                />
            </el-form-item>
        </Motion>
        <!-- 密码 -->
        <Motion :delay="150">
            <el-form-item prop="password">
                <el-input
                    v-model="form.password"
                    :prefix-icon="useRenderIcon(Lock)"
                    type="password"
                    :placeholder="$t('login.password')"
                    show-password
                    clearable
                />
            </el-form-item>
        </Motion>
        <!-- 验证码 -->
        <Motion :delay="200">
            <el-form-item prop="captchaText">
                <el-input
                    v-model="form.captchaText"
                    :prefix-icon="useRenderIcon(KeyHole)"
                    :placeholder="$t('login.verifyCode')"
                    clearable
                >
                    <template #append>
                        <img :src="captchaImage" alt="captcha" @click="getCaptcha" />
                    </template>
                </el-input>
            </el-form-item>
        </Motion>
        <!-- 记住我 -->
        <Motion :delay="250">
            <el-form-item>
                <div class="w-full h-[20px] flex justify-between items-center">
                    <el-checkbox v-model="checked" size="small">
                        <span class="flex items-center text-sm">
                            7 {{ $t("login.remember") }}
                            <span
                                v-tippy="{
                                    content: $t('login.rememberInfo'),
                                    placement: 'top'
                                }"
                                class="icon-[ri--information-line] ml-1 text-base"
                            />
                        </span>
                    </el-checkbox>
                    <!-- 忘记密码 -->
                    <el-button link type="primary">
                        {{ $t("login.forget") }}
                    </el-button>
                </div>
            </el-form-item>
            <!-- 登录按钮 -->
            <!-- Note[tailwindcss] 类名前面加一个 ! 表示 important -->
            <el-button
                class="w-full mb-5"
                type="primary"
                size="default"
                :loading="loginLoading"
                @click="onLogin"
            >
                {{ $t("login.login") }}
            </el-button>
        </Motion>
        <!-- 操作按钮 -->
        <Motion :delay="300">
            <el-form-item>
                <div class="w-full h-[20px] mt-2 flex justify-between items-center">
                    <el-button
                        v-for="(item, index) in operates"
                        :key="index"
                        class="w-full mt-4"
                        size="default"
                        @click="useUserStore().SET_CURRENT_PAGE(index + 1)"
                    >
                        {{ $t(item.title) }}
                    </el-button>
                </div>
            </el-form-item>
        </Motion>
        <!-- 第三方登录 -->
        <Motion :delay="350">
            <el-form-item>
                <el-divider>
                    <p class="text-gray-500 text-xs">
                        {{ $t("login.thirdLogin") }}
                    </p>
                </el-divider>
                <div class="w-full flex justify-evenly">
                    <span v-for="(item, index) in thirdParty" :key="index" :title="$t(item.title)">
                        <span :class="item.icon" class="cursor-pointer text-[20px] text-gray-500 hover:text-(--el-color-primary)" />
                    </span>
                </div>
            </el-form-item>
        </Motion>
    </el-form>
</template>
